// promise中处理异步逻辑
//  方法：在then方法中，将then的两个参数(函数)保存起来，等异步代码执行完，就可以使用储存的函数了
//  问题: 此时同一个Promise实例只能调用一次then方法，想要调用多次，看myPromise3.js

// 维护三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {


  // executor 执行器函数，参数为resolve函数，reject函数
  constructor(executor) { //executor立即执行
    executor(this.resolve, this.reject);
  }

  status = PENDING;// 默认状态
  value = undefined;//成功之后的值 - 使用方传入
  reason = undefined;//失败的原因 - 使用方传入

  successCallback = undefined;//成功回调
  failCallback = undefined;// 失败回调


  // 直接调用一个函数(不使用点调用)，那么该函数中的this指向window或undefiend
  // 注意：函数作为类的属性，通常使用箭头函数,这样，直接调用函数时(不使用点调用)，该函数中的this就始终指向该对象的实例
  resolve = value => {
    this.value = value;
    // 保证状态只能被修改一次
    if (this.status !== PENDING) {
      return;
    }
    this.status = FULFILLED;
    // successCallback存在，则调用一次successCallback
    // 不存在，说明没有异步逻辑执行
    this.successCallback && this.successCallback(this.value);
  };
  reject = reason => {
    this.reason = reason;
    // 保证状态只能被修改一次
    if (this.status !== PENDING) {
      return;
    }
    this.status = REJECTED;
    // failCallback存在，则调用一次failCallback
    // 不存在，说明没有异步逻辑执行
    this.failCallback && this.failCallback(this.reason);
  };

  // then是被定义在原型对象中的，在对象的原型对象中定义函数then的写法: then(){} ; 非箭头函数
  // 判断状态，并决定执行resolve还是reject
  then(successCallback, failCallback) {
    if (this.status === FULFILLED) {
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      failCallback(this.reason);
    } else {
      // 此处如果执行，说明一定存在异步代码
      // PENDING状态
      this.successCallback = successCallback;
      this.failCallback = failCallback;
    }
  }
}

module.exports = MyPromise;